#pragma once

#include "Chart.h"

namespace ARAP
{
	/**
	 * @file ARAPBuilder.h
	 * @author xingyifan
	 * @date 2023-08-17 14:53
	 *
	 * @description: ARAP 构建器
	 */

	class ARAPBuilder
	{
	private:
		struct HalfedgeData
		{
			double cot;
			MatrixXx1 dx;

			HalfedgeData() : cot(0) { dx.resize(2); }
		};

		Mesh* m_mesh;
		const std::vector<LSCM::Chart>& m_charts;

		// 加权，确保矩阵非奇异
		double m_lambda;

		// 保存预分解的配置矩阵
		Eigen::SimplicialLDLT<SparseMatrix> m_solver;

		// 句柄，用于增加属性值
		OpenMesh::HPropHandleT<HalfedgeData> m_halfedgeData;
		OpenMesh::FPropHandleT<MatrixX> m_Lts;
		OpenMesh::FPropHandleT<int> m_chartIds;
		OpenMesh::VPropHandleT<int> m_ids;

	public:
		ARAPBuilder(Mesh* mesh, const std::vector<LSCM::Chart>& charts, double lambda);
		~ARAPBuilder();

		void Build(int times);

	private:
		SparseMatrix initializeData(const LSCM::Chart& chart);
		void localPhase(const LSCM::Chart& chart);
		void globalPhase(const LSCM::Chart& chart, const SparseMatrix& M);
		void storeUVs(const LSCM::Chart& chart);
	};
} // namespace ARAP
